#ifndef _DBBPTR_H_
#define _DBBPTR_H_

#include "dbb.h"

//------------------------------------------------------------------------
template<typename T>
class Ptr
{
public:
	Ptr();
	Ptr(T* obj);
	Ptr(const Ptr<T>& p);
	~Ptr();

	void	operator= (T* obj);
	void	operator= (const Ptr<T>& p);

	bool	operator==(T* obj) const;
	bool	operator==(const Ptr<T>& p) const;

	bool	operator!=(T* obj) const;
	bool	operator!=(const Ptr<T>& p) const;

	T*		operator->() const;
	T&		operator* () const;
	operator T*() const;
	T*		get() const;
	
	bool	isValid() const;

private:
	T*		m_ptr;
};

//------------------------------------------------------------------------
template<typename T>
Ptr<T>::Ptr()
:m_ptr(DBBNULL)
{

}

//------------------------------------------------------------------------
template<typename T>
Ptr<T>::Ptr(T* obj)
:m_ptr(obj)
{
	if(DBBNULL!=m_ptr)
	{
		m_ptr->addReference();
	}
}

//------------------------------------------------------------------------
template<typename T>
Ptr<T>::Ptr(const Ptr<T>& p)
:m_ptr(p.m_ptr)
{
	if(DBBNULL!=m_ptr)
	{
		m_ptr->addReference();
	}
}

//------------------------------------------------------------------------
template<typename T>
Ptr<T>::~Ptr()
{
	if(DBBNULL!=m_ptr)
	{
		m_ptr->releaseReference();
		m_ptr = DBBNULL;
	}
}

//------------------------------------------------------------------------
template<typename T> void
Ptr<T>::operator= (T* obj)
{
	if(m_ptr!=obj)
	{
		if(DBBNULL!=m_ptr)
		{
			m_ptr->releaseReference();
		}
		m_ptr = obj;
		if(DBBNULL!=m_ptr)
		{
			m_ptr->addReference();
		}
	}
}

//------------------------------------------------------------------------
template<typename T> void
Ptr<T>::operator= (const Ptr<T>& p)
{
	if(m_ptr!=p.m_ptr)
	{
		if(DBBNULL!=m_ptr)
		{
			m_ptr->releaseReference();
		}
		m_ptr = p.m_ptr;
		if(DBBNULL!=m_ptr)
		{
			m_ptr->addReference();
		}
	}
}

//------------------------------------------------------------------------
template<typename T> bool
Ptr<T>::operator==(T* obj) const
{
	return m_ptr==obj;
}

//------------------------------------------------------------------------
template<typename T> bool
Ptr<T>::operator==(const Ptr<T>& p) const
{
	return m_ptr==p.m_ptr;
}

//------------------------------------------------------------------------
template<typename T> bool
Ptr<T>::operator!=(T* obj) const
{
	return m_ptr!=obj;
}

//------------------------------------------------------------------------
template<typename T> bool
Ptr<T>::operator!=(const Ptr<T>& p) const
{
	return m_ptr!=p.m_ptr;
}

//------------------------------------------------------------------------
template<typename T> T*
Ptr<T>::operator->() const
{
	dbbassert(DBBNULL!=m_ptr);
	return m_ptr;
}

//------------------------------------------------------------------------
template<typename T> T&
Ptr<T>::operator* () const
{
	dbbassert(DBBNULL!=m_ptr);
	return *m_ptr;
}

//------------------------------------------------------------------------
template<typename T>
Ptr<T>::operator T*() const
{
	return m_ptr;
}

//------------------------------------------------------------------------
template<typename T> T*
Ptr<T>::get() const
{
	return m_ptr;
}

//------------------------------------------------------------------------
template<typename T> bool
Ptr<T>::isValid() const
{
	return m_ptr!=DBBNULL;
}

#endif